/*
    Title:  SD1731 driver for Maxim temperature sensor
	Purpose: test microchip i2c hardware library
	by: Rolf Ziegler
	Date: July 2010
  
	Input: RB0+RB1 of pic 18f4550
	Oupout: Subroutine returning 1 word with temperature of chip
			or temperature in 1/100 deg.
*/


//#define SENSOR_ADDRESS 0x9E

#include <p18f4550.h>
#include <i2c.h>

#include <delays.h>
#include "typedef.h"
#include "lsm303_driver.h"

#define  SDA_IN     TRISBbits.TRISB0 = 1 // define macro for data pin output
#define  SCL_IN    TRISBbits.TRISB1 = 1 // define macro for data pin input


void delayi2c(void)
{  //delay between i2c writes
 //Delay10TCYx(25); //delays 250 clock cycles = 50us delay at 20MHz clock
 Delay10TCYx(50); //delays 500 clock cycles = 41us delay at 48MHz clock
}

signed char WriteI2C( unsigned char data_out );

void lsm303Init(void) {

   SDA_IN;
   SCL_IN;

   OpenI2C(MASTER,SLEW_OFF);

   SSPSTAT=0x80;
   SSPADD = 40;

}
   

u8 i2cReady(void)
{
   u8 ack;
//   LedR=0;
   StartI2C();            // If the write command is acknowledged,
   ack = WriteI2C(ACCEL);  // then the device is ready.
   StopI2C();
   return !ack;
//   LedR=1;
}


void i2cWriteByte(u8 device,u8 address, u8 data)
{
//   while(!ds1731_rdy());
   StartI2C();
   IdleI2C();
   WriteI2C(device);
   IdleI2C();
   WriteI2C(address);
   IdleI2C();
   WriteI2C(data);
   IdleI2C();
   StopI2C();
}


u8 i2cReadByte(u8 device,u8 address)
{
   u8 data;

   StartI2C();
   IdleI2C();
   WriteI2C(device);
   IdleI2C();
   WriteI2C(address);
   IdleI2C();
   RestartI2C();
   IdleI2C();
   WriteI2C(device+1);
   IdleI2C();
   data=ReadI2C();
   IdleI2C();
   StopI2C();
   return(data);
}

u16 i2cReadWord(u8 device,u8 address)
{
   int data;

   StartI2C();
   IdleI2C();
   WriteI2C(device);
   IdleI2C();
   WriteI2C(address);
   IdleI2C();
   RestartI2C();
   IdleI2C();
   WriteI2C(device+1);
   IdleI2C();
   data=(int)ReadI2C()<<8;
   AckI2C();
   IdleI2C();
   data+=(int)ReadI2C();
   NotAckI2C();
   IdleI2C();
   StopI2C();
   return((int)data);
}


signed char WriteI2C( unsigned char data_out )
{
  SSPBUF = data_out;           // write single byte to SSPBUF
  if ( SSPCON1bits.WCOL )      // test if write collision occurred
   return ( -1 );              // if WCOL bit is set return negative #
  else
  {
	if( ((SSPCON1&0x0F)!=0x08) && ((SSPCON1&0x0F)!=0x0B) )	//Slave mode only
	{
	      SSPCON1bits.CKP = 1;        // release clock line
	      while ( !PIR1bits.SSPIF );  // wait until ninth clock pulse received

	      if ( ( !SSPSTATbits.R_W ) && ( !SSPSTATbits.BF ) )// if R/W=0 and BF=0, NOT ACK was received
	      {
	        return ( -2 );           //return NACK
	      }
		  else
		  {
			return ( 0 );				//return ACK
		  }
	}
	else if( ((SSPCON1&0x0F)==0x08) || ((SSPCON1&0x0F)==0x0B) )	//master mode only
	{
	    while( SSPSTATbits.BF );   // wait until write cycle is complete
	    IdleI2C();                 // ensure module is idle
	    if ( SSPCON2bits.ACKSTAT ) // test for ACK condition received
	    	 return ( -2 );			// return NACK
		else return ( 0 );              //return ACK
	}

  }
}


////////////////////// end of driver file /////////////////////////////////////
